import path from 'path';
import fs from 'fs';
import glob from 'glob';
import { baseConsoleCommander } from '../baseConsoleCommander';
import { rule } from '../..';
import { WebController } from '../WebController';
import mkdirp from 'mkdirp';
import chalk from 'chalk';

export default baseConsoleCommander({
  commands() {
    this
      .create('export:routes')
      .showInHelp()
      .docs({
        description: 'Export web routes to file and `ctx.state.routes`',
      })
      .options({
        dir: rule.array.each(rule.string).minItemLength(1).docs({
          description: 'The folders where web routes come from',
        }),
        output: rule
          .string
          .default('./routes.json')
          .docs({
            description: 'The file path JSON data will output to.',
          }),
      })
      .alias({
        output: 'o',
      })
      .action((ctx) => {
        let { dir: routesPath, output } = ctx.options;
        const routes: object[] = [];
        const now = Date.now();

        routesPath = routesPath.map((item) => path.resolve(item));
        output = path.resolve(output);

        routesPath.forEach((routePath) => {
          glob.sync(path.join(routePath, '**/!(*.d).{ts,js}')).forEach((matchPath) => {
            const modules = require(matchPath);
            console.log('Parsing path: ' + matchPath);

            Object.values(modules).forEach((item) => {
              if (item && item instanceof WebController) {
                item.registerActions();
                item.builders.forEach((builder) => {
                  routes.push(builder.toJSON());
                });
              }
            });
          });
        });

        const dir = path.dirname(output);
        if (!fs.existsSync(dir)) {
          mkdirp.sync(dir);
        }

        fs.writeFileSync(output, JSON.stringify(routes, null, 4));
        Object.assign(ctx.state, {
          routes,
        });

        console.log(chalk.bold.greenBright(`[${Date.now() - now}ms] Output to: `) + output);
      });
  },
})
